home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / MISC / MAG06.ZIP / MAG06.TXT
Encoding:
Text File  |  1996-03-11  |  37.7 KB  |  891 lines

  1. Spellcaster presents:
  2.  
  3.  
  4. TTTTTTTTTT HH      HH EEEEEEEEEE    MM      MM    AAAA     GGGGGGGGG
  5.     TT     HH      HH EE            MMM    MMM   AA  AA   GG
  6.     TT     HH      HH EE            MM M  M MM  AA    AA  GG  
  7.     TT     HHHHHHHHHH EEEEEE        MM  MM  MM  AAAAAAAA  GG   
  8.     TT     HH      HH EE            MM      MM  AA    AA  GG    GGGG
  9.     TT     HH      HH EE            MM      MM  AA    AA  GG      GG
  10.     TT     HH      HH EEEEEEEEEE    MM      MM  AA    AA   GGGGGGGG
  11.  
  12.                                                         Issue 6
  13.                                                         8-3-96
  14.  
  15.  
  16.  
  17.   Index
  18.  
  19.         1. Introduction
  20.           1.1. About the magazine
  21.           1.2. About the author
  22.           1.3. Distribution
  23.           1.4. Contribuitions
  24.           1.5. Hellos and greets
  25.         2. Records and basic file handling
  26.           2.1. Records
  27.           2.2. Files
  28.         3. The dos and don'ts of file acessing
  29.         4. Scrolling in text mode
  30.         5. Graphics Part V - Loading a PCX file
  31.           5.1. Introduction
  32.           5.2. The PCX file structure
  33.           5.3. Decoding a PCX file
  34.         6. Hints and tips
  35.         7. Points of view
  36.         8. The adventures of Spellcaster, part 6
  37.  
  38.   1. Introduction
  39.  
  40.     1.1. About the magazine
  41.  
  42.     Welcome to number 6 of 'The Mag', brought to you, as usual, by Spellcaster,
  43.   alias Diogo de Andrade. I know this issue is VERY late, but I got some exams
  44.   and then my hard drive just cocked out... It still doesn't work, so I'm
  45.   writing this in  the school's computers, that are a piece of shit, and I've
  46.   very pissed ! It's the second time I write issue 6, because I already had
  47.   finished it when my hard drive died...
  48.     This magazine is dedicated to all the programmers and would-be programmers
  49.   out there, especially to those that can't access the Net easily to get
  50.   valuable information, to those who wish to learn how to program anything,
  51.   from demos to games, passing through utilities and all sort of thing your
  52.   mind can think of, and to those that can't find the right information.
  53.  
  54.     I've made an error in the previous issues. In the virtual screens part,
  55.   there's a small piece of code that reads:
  56.  
  57.     Procedure InitVirt;
  58.     Var A:Byte;
  59.     Begin
  60.          For A:=1 To Npages Do
  61.          Begin
  62.               GetMem(Virt[A],64000);
  63.               VP[A]:=Segment(Virt[A]^);
  64.          End;
  65.     End.
  66.  
  67.     You should change the Segment keyword to Seg... Small mistake... You should
  68.   read now:
  69.  
  70.     Procedure InitVirt;
  71.     Var A:Byte;
  72.     Begin
  73.          For A:=1 To Npages Do
  74.          Begin
  75.               GetMem(Virt[A],64000);
  76.               VP[A]:=Seg(Virt[A]^);
  77.          End;
  78.     End.
  79.  
  80.     Sorry about that... I'm only human...
  81.  
  82.     When you read this magazine, I'll assume some things. First, I assume you
  83.   have Borland's Turbo Pascal, version 6 and upwards (and TASM for the assembly
  84.   tutorials). I'll also think you have a 80386 (or 386 for short; a 486 would
  85.   be even better), a load of patience and a sense of humor. This last is almost
  86.   essencial, because I don't receive any money for doing this, so I must have
  87.   fun doing it. I will also take for certain you have the 9th grade (or
  88.   equivelent). Finally, I will assume that you have the last issues of
  89.   'The Mag', and that you have grasped the concepts I tried to transmit. If
  90.   you don't have the issues, you can get them by mail, writing to one of the
  91.   adresses shown below (Snail mail and Email).
  92.  
  93.     As I stated above, this magazine will be made especially for those who don't
  94.   know where to get information, or want it all in the same place, and to those
  95.   who want to learn how to program, so I'll try to build knowledge, building up
  96.   your skills issue by issue. If you sometimes fail to grasp some concept, don't
  97.   despair; try to work it out.
  98.     That's what I did... Almost everything I know was learnt from painfull
  99.   experience. If you re-re-re-read the article, and still can't understand it,
  100.   just drop a line, by mail, or just plain forget it. Most of the things I 
  101.   try to teach here aren't linked to each other (unless I say so), so if you
  102.   don't understand something, skip it and go back to it some weeks later. It
  103.   should be clearer for you then. Likewise, if you see any terms or words you 
  104.   don't understand, follow the same measures as before.
  105.  
  106.     Ok, as I'm earing the Net gurus and other god-like creatures talking
  107.   already, I'm just going to explain why I use Pascal.
  108.   For starters, Pascal is a very good language, ideal for the beginner, like 
  109.   BASIC (yech!), but it's powerfull enough to make top-notch programms.
  110.   Also, I'll will be using assembly language in later issues, and Pascal makes
  111.   it so EASY to use. 
  112.   Finally, if you don't like my choice of language, you can stop whining. The
  113.   teory behind each article is very simple, and common with any of the main
  114.   languages (C, C++, Assembly - Yes, that's true... BASIC isn't a decent
  115.   language).
  116.  
  117.     Just one last thing... The final part of the magazine is a little story
  118.   made up by my distorted mind. It's just a little humor I like to write, and
  119.   it hasn't got nothing to do with programming (well, it has a little), but, 
  120.   as I said before, I just like to write it.
  121.  
  122.     1.2. About the author
  123.  
  124.     Ok, so I'm a little egocentric, but tell me... If you had the trouble of 
  125.   writing hundreds of lines, wouldn't you like someone to know you, even by 
  126.   name ?
  127.  
  128.     My name is Diogo de Andrade, alias Spellcaster, and I'm the creator, 
  129.   editor and writer of this magazine. 
  130.     I live in a small town called Setúbal, just near Lisbon, the capital of
  131.   Portugal... If you don't know where it is, get an encyclopedia, and look for
  132.   Europe. Then, look for Spain. Next to it, there's Portugal, and Setúbal is in
  133.   the middle.
  134.  
  135.     I'm 18 years old, and I just made it in to the university (if you do want
  136.   to know, I'm in the Technical Institute of Lisbon, Portugal), so I'm not 
  137.   a God-Like creature, with dozens of years of practice (I only program by 
  138.   eight years now, and I started in a Spectrum, progressing later to an Amiga.
  139.   I only program in the PC for a year or so), with a mega-computer (I own a 
  140.   386SX, 16 Mhz), that wear glasses with lens that look like the bottom of a 
  141.   bottle (I use glasses, but only sometimes), that has his head bigger than a 
  142.   pumpkin (I have a normal sized head) and with an IQ of over 220 (mine is 
  143.   actually something like 180). I can program in C, C++, Pascal, Assembly 
  144.   and even BASIC (yech!).
  145.  
  146.     So, if I am a normal person, why do I spend time writing this ?
  147.   Well, because I have the insane urge to write thousands of words every now
  148.   and then, and while I'm at it, I may do something productive, like teaching
  149.   someone. I may be young, but I know a lot about computers (how humble I am;
  150.   I know, modesty isn't one of my qualities).
  151.  
  152.     Just one more thing, if you ever program anything, please send to me... I
  153.   would love to see some work you got, maybe I could learn something with it.
  154.   Also, give me a greet in your program/game/demo... I love seeing my name.
  155.  
  156.     1.3. Distribution
  157.  
  158.     I don't really know when can I do another issue, so, there isn't a fixed
  159.   space of time between two issues. General rule, I will try to do one every two
  160.   weeks, maybe more, probably less (Eheheheh).
  161.     'The Mag' is available by the following means:
  162.  
  163.     - Snail Mail : My address is below, in the Contributions seccion... Just
  164.                    send me a disk and tell me what issues you want, and I
  165.                    will send you them...
  166.  
  167.     - E-Mail : If you E-mail me and ask me for some issues, I will Email you
  168.                back with the relevant issues attached.
  169.  
  170.     - BBS's : I don't know for sure what BBS's have or will have my magazine,
  171.               but I will try to post it in the Skyship BBS.
  172.               If you have a BBS and you want to receive 'The Mag', contact me.
  173.  
  174.                  Skyship BBS numbers: (351)+01-3158088
  175.                                       (351)+01-3151435
  176.  
  177.     - Internet : You can access the Spellcaster page and take the issues out
  178.                  of there in:
  179.  
  180.                  http://alfa.ist.utl.pt/~l42686
  181.  
  182.     1.4. Contributions
  183.  
  184.     I as I stated before, I'm not a God... I do make mistakes, and I don't 
  185.   have (always) the best way of doing things. So, if you think you've spotted
  186.   an error, or you have thought of a better way of doing things, let me know.
  187.   I'll be happy to receive anything, even if it is just mail saying 'Keep it 
  188.   up'. As all human beings, I need incentive.
  189.  
  190.     Also, if you do like to write, please do... Send in articles, they will be
  191.   welcome, and you will have the chance to see your names up in lights.
  192.     They can be about anything, for a review of a book or program that can
  193.   help a programmer, to a point of view or a moan. I'm specially interested in
  194.   articles explaining XMS, EMS, DMA and Soundblaster/GUS.
  195.  
  196.     If anyone out there has a question or wants to see an article about 
  197.   something in particular, feel free to write... All letters will be answered,
  198.   provided you give me your address.
  199.  
  200.     I'm also trying to start a new demo/game/utility group, and I need all sort 
  201.   of people, from coders (sometimes, one isn't enough), musicians (I can 
  202.   compose, but I'm a bit limited), graphics artists (I can't draw nothing) and
  203.   spreaders... I mean, by a spreader, someone who spreads things, like this mag.
  204.   If you have a BBS and you want it to include this magazine, feel free to
  205.   write me...
  206.  
  207.     You can also contact me personally, if you study on the IST (if you don't
  208.   know what the IST is, you don't study there). I'm the freshman with the
  209.   black hair and dark-brown eyes... The one who's skipping classes...
  210.   I recommend you to contact me personally, if you can, especially if you
  211.   are a member of the opposite sex (I'm a man, for those of you who are
  212.   wondering).
  213.  
  214.     My adress is:
  215.                  Praceta Carlos Manito Torres, nº4/6ºC
  216.                  2900 Setúbal
  217.                  Portugal
  218.  
  219.     Email: dgan@rnl.ist.utl
  220.            l42686@alfa.ist.utl.pt
  221.  
  222.     And if you want to contact me on the lighter side, get into one of the
  223.   following talkers... To do that telnet to:
  224.  
  225.           Lost Eden -> Ubistc.Ubi.Pt    : Port 1414
  226.  
  227.               Talho -> Ubistc.Ubi.Pt    : Port 7000
  228.  
  229.               CItal -> Zeus.Ci.Ua.Pt    : Port 6969
  230.  
  231.     I'm almost always there in the afternoon... As you may have guessed already,
  232.   my handle is Spellcaster (I wonder why...)...
  233.  
  234.     1.5. Hellos and greets
  235.  
  236.     I'll say hellos and thanks to all my friend, especially for those who put 
  237.   up with my constant whining:
  238.     Special greets go to Denthor from Asphyxia (for the excelent VGA trainers),
  239.   Draeden from VLA (for assembly tutorials), Joaquim Elder Guerreiro, alias
  240.   Dr.Shadow (Delta Team is still up), Alex "Darkfox" (thanks for letting me
  241.   use your BBS), Joäo Neves for sugestions, testing and BBS services, and all
  242.   the demo groups out there.
  243.     I will also send greets to everybody that responded to my mag... Thank
  244.   you very much !
  245.  
  246.  
  247.   2. Records and basic file handling
  248.  
  249.     Ok, this article is about files and records... First, I'll talk about
  250.  
  251.     2.1. Records
  252.  
  253.     Well, records are... ahh...er... records... I know this wasn't helpfull,
  254.   but the best way to describe records is with an example. Imagine you wanted
  255.   to build a program to keep track of all your friends' adresses and phone
  256.   numbers. With the knowledge you have (assuming that you only know what I've
  257.   been teaching you), you would have to do something like this:
  258.  
  259.        Var Names:Array[1..100] of String;
  260.            Phone:Array[1..100] of String;
  261.            Adress:Array[1..100] of String;
  262.  
  263.   Or something like this:
  264.  
  265.        Var Data:Array[1..100,1..3] of String;
  266.  
  267.     But this solution has several drawbacks... In the second example, you would
  268.   have to remember that index 2 was the phone number and index 3 was the adress.
  269.     With records, things get easier and simpler... You just have to make
  270.   something like this:
  271.  
  272.        Type DataRec=Record
  273.                           Name:String;
  274.                           Phone:String;
  275.                           Adress:String;
  276.                     End;
  277.  
  278.        Var Data:Array[1..100] of DataRec;
  279.  
  280.     Now, you have an array called Data full of records... You can now access
  281.   data in a perfectly straighward form...
  282.  
  283.        Data[1].Name:='Spellcaster';
  284.        Data[1].Phone:='01-551155';
  285.  
  286.     They are treated as normal variables... The Name, Phone and Adress are the
  287.   fields of record DataRec.
  288.     This is an invalubale resource when building programs... I use them all the
  289.   time.
  290.     I think this is fairly simple, so I'll go on to
  291.  
  292.     2.2. Files
  293.  
  294.     There will come a time in your programming experiences that you'll have the
  295.   need to access files in your computer, to read a picture, for instance. When
  296.   that time comes, you better be prepared, so read this carefully... This is
  297.   very basic file accessing, and it's only usefull to read some types of data.
  298.   You can't use these concepts to read a PCX file. Read the next article for
  299.   that.
  300.     There is a special kind of variable, called the Text type variable, that is
  301.   used to read ASCII coded text. It is declared as usual variables, but it isn't
  302.   used like them...
  303.     I'll do a small demonstration commented program, to exemplify...
  304.  
  305.     Program Test_18;                  { This program gets string from the }
  306.                                       { user and dumps them to a file, called }
  307.                                       { SPELL.TXT... The program ends when the }
  308.                                       { user returns an empty string.}
  309.     Var F:Text;                       { Defines variable F of type text }
  310.         S:String;                     { Defines S as a string }
  311.  
  312.     Begin
  313.          Assign(F,'Spell.Txt');       { Associates variable with file }
  314.                                       { SPELL.TXT. It isn't important if the }
  315.                                       { file exists or not... }
  316.          ReWrite(F);                  { This sets up the file F for writing. }
  317.          Repeat
  318.                ReadLn(S);
  319.                WriteLn(F,S);          { This writes the content of varible S }
  320.                                       { to file F... }
  321.          Until S='';
  322.          Close(F);                    { This closes file F, and saves the }
  323.                                       { changes made to it... }
  324.     End.
  325.  
  326.     Now, another example...
  327.  
  328.     Program Test_19;                  { This program reads the contents of }
  329.                                       { file MAG06.TXT and dumps it in the }
  330.                                       { screen... }
  331.     Var F:Text;                       { Defines variable F as type Text }
  332.         S:String;                     { Defines var S as a string }
  333.  
  334.     Begin
  335.          Assign(F,'Mag06.txt');       { Associates var F with file MAG06.TXT }
  336.          Reset(F);                    { Prepares file F for reading. If the }
  337.                                       { file doesn't exist, the program will }
  338.                                       { give you an error message. }
  339.          Repeat
  340.                Readln(F,S);           { This reads a string from file F, and }
  341.                WriteLn(S);            { stores it in var S }
  342.          Until Eof(F);                { Repeats until End Of File F... }
  343.          Close(F)                     { Closes file F }
  344.     End;
  345.  
  346.     So, I think this is simple, even for a beginner... The Writeln and Readln
  347.   procedures do the input and output to the file. The Reset and Rewrite keywords
  348.   prepare the file for reading and writing. Notice that a file can't be open
  349.   for reading AND writing simultaniously. The EOF function returns True if
  350.   the file has already been totally read...
  351.     Now, imagine you already had a file, and you wanted to add something in
  352.   the end of it... Then you could use the Append keyword, instead of the Rewrite
  353.   keyword. The difference between them is that Rewrite overwrites an existing
  354.   file, and Append adds the data in the end.
  355.     One last remark about files... In Pascal, all files are sequencial... This
  356.   means that you, in order to access data in the middle, must access the data
  357.   in the begginning. This also means you can't add data to the middle of a
  358.   file.
  359.  
  360.  
  361.  
  362.   3. The dos and don'ts of file acessing
  363.  
  364.     This article is an extension to the last one... It develops further more
  365.   the concept of files. It teachs you to access files of other types besides
  366.   text files... The name doesn't have nothing to do with the article itself,
  367.   but I liked the idea...
  368.  
  369.     Imagine you wanted to access a file and get a byte at a time... This would
  370.   be impossible with variables of type text. So, variables of type file come
  371.   into action... Variables of type file are similar to varibles of type text,
  372.   but more flexible... It enables to read a specified number of bytes to a
  373.   variable, instead of reading entire lines...
  374.     As usual, I'll suply you with an example... You know the say: An example
  375.   is worth more than a thousand bytes of text...
  376.  
  377.     Program Test_20;
  378.  
  379.     Var F:File;
  380.         A:Array[1..20] Of Integer;
  381.         B:Integer;
  382.  
  383.     Begin
  384.          Assign(F,'Spell.Dat');
  385.          Rewrite(F,1);
  386.          For B:=1 To 20 Do A[B]:=Random(100);
  387.          Blockwrite(F,A,Sizeof(A));
  388.          Close(F);
  389.     End.
  390.  
  391.     This little program generates an array with 20 random integers and 
  392.   then it saves them to a file called 'Spell.Dat'.
  393.     The Random(n) function gives a random integer in the 0..n range.
  394.     The Blockwrite(File, Variable, Bytes) writes a certain number of 
  395.   Bytes that are stored away on the Variable to a certain File. The 
  396.   Variable can be any kind of variable, including user-defined variables.
  397.     This is an unvaluble resource. I use BlockWrite and it's counterpart 
  398.   BlockRead in almost every program I make.
  399.  
  400.  
  401.     Program Test_21;
  402.  
  403.     Var F:File;
  404.         A:Array[1..20] Of Integer;
  405.         B:Integer;
  406.  
  407.     Begin
  408.          Assign(F,'Spell.Dat');
  409.          Reset(F,1);
  410.          Blockread(F, A, Sizeof(A));
  411.          Close(F);
  412.          For B:=1 To 20 Do Writeln(A[B]);
  413.          Readln;
  414.     End.
  415.  
  416.     The above example reads the file created with the other program and 
  417.   stores it on the array A. Then it types the values to the screen.
  418.     Just one more thing I forgot to mention: You probably noticed the 
  419.   different sintax of the Reset and the Rewrite keywords. I'm not sure 
  420.   about what does it mean the number in front of the file identifier, but I 
  421.   think it is the number of bytes to read at any one time. I always read
  422.   1 byte at a time, so I always put a 1. If anyone smarter than me knows 
  423.   what is that number, mail me !
  424.     I'll finish this article with a piece of code I've been using for the
  425.   last two issues sample programs. The procedure LoadPal reads a palette from
  426.   disk and stores it in a RGBList (see the issue that talks about palette
  427.   manipulation).
  428.  
  429.     Procedure LoadPal(Filename:String;Var Pal:RgbList);
  430.     Var F:File;
  431.     Begin
  432.          Assign(F,Filename);
  433.          Reset(F,1);
  434.          Blockread(F,Pal,768);
  435.          Close(F);
  436.     End;
  437.  
  438.     This piece of code is pretty straightforward stuff, I think.
  439.  
  440.  
  441.   4. Scrolling in text mode
  442.  
  443.     Ok... This is a tricky article to understand and to write. So I'll 
  444.   try to do it the best I can. I wrote it because a reader asked it.
  445.     This article is writen with the thought that you are understanding 
  446.   the graphics tutorials.
  447.     Text mode can be thought as similar to mode 13h, in the respect that 
  448.   you could make a direct access to it, using the Mem keyword. The 
  449.   differences are that the address of a text screen is B000h, instead of 
  450.   A000h. Besides that, while $A000:0000 represented the first pixel on the 
  451.   screen in mode 13h, $B800:0000 represents the first character on the 
  452.   screen. 
  453.     Moving on, we need to know with the VGA card registers. For scrolling 
  454.   the text screen, we need to know this one:
  455.  
  456. --------------------------------------------------------------------------------
  457. Port-Index: 08h              Port: 03d4h/3d5h
  458. usage:      Preset row scan
  459.             d7    Unused
  460.             d6    Byte panning control
  461.             d5    Byte panning control
  462.             d0-d4 Preset row scan
  463. Description: This changes the first row of pixels to be displayed. For 
  464.              this article, we only need to know that if you do 
  465.                Port[$03d4]:=8; 
  466.                Port[$03d5]:=n;
  467.              the first pixel to be desplayed on the screen 
  468.              would be n. 
  469. --------------------------------------------------------------------------------
  470.  
  471.     So, knowing this, the general algorythm is:
  472.  
  473.       You put the image, or whatever you want to scroll in in address 
  474.         $B800:4000. This is just out of the visual screen.
  475.   |-> You scroll the screen, by changing the first pixel to be desplayed.
  476.   |   When you have scrolled sixteen pixels, you scroll in the memory the 
  477.   |     image you want to scroll in, this is, you move the memory from 
  478.   |     $B800:0160 to $B800:0000.
  479.   |    You go back to here
  480.   |                    |
  481.   ----------------------
  482.  
  483.     Following this there is a piece of code that implements the above 
  484.   algorythm. It is unoptimized. Experiment with it... Change the 
  485.   values... Do something with it... This won't crash the computer... I 
  486.   think... :)
  487.  
  488.     Program Test_22;
  489.  
  490.     {$X+}
  491.  
  492.     Uses Crt;
  493.  
  494.     Var F:File;
  495.         Old:Byte;
  496.         N,M:Integer;
  497.  
  498.     Procedure WaitVbl; Assembler;
  499.     Label l1,l2;
  500.     Asm
  501.        mov dx,3dah
  502.        l1:
  503.           in al,dx
  504.           and al,08h
  505.           jnz l1
  506.        l2:
  507.           in al,dx
  508.           and al,08h
  509.           jz l2
  510.     End;
  511.  
  512.     Begin
  513.          Port[$3d4]:=8;
  514.          Old:=Port[$3d5];  {This saves the old value... It is usually one...}
  515.          Fillchar(Mem[$B800:4000],16000,0);  { This makes the image I
  516.                                                want to scroll in be just a
  517.                                                screen full of exlamation
  518.                                                points... }
  519.          For M:=0 To 50 Do
  520.          Begin
  521.               For N:=0 To 15 Do
  522.               Begin
  523.                    Port[$3d4]:=8;
  524.                    Port[$3d5]:=N;
  525.                    WaitVbl;
  526.               End;
  527.               Port[$3d4]:=8;
  528.               Port[$3d5]:=0;
  529.               Move(Mem[$B800:160],Mem[$B800:0],16000);
  530.          End;
  531.          Readkey;
  532.          Port[$3d4]:=8;
  533.          Port[$3d5]:=Old;
  534.     End.
  535.  
  536.  
  537.  
  538.   5. Graphics Part V - Loading a PCX file
  539.  
  540.     5.1. Introduction
  541.  
  542.     Ok, this is part 5 of the Graphics In Mode 13h tutorial. This 
  543.   issues's article is about reading a PCX file. This is quite simple, as 
  544.   reading any kind of file... You just have to know the file's structure.
  545.     Just for knowledge, the PCX file format was created by ZSoft, for their
  546.   popular drawing program, PaintBrush... I don't know what makes it popular,
  547.   because I prefer Electronic Art's Deluxe Paint II anytime !
  548.   
  549.     5.2. The PCX's file structure
  550.  
  551.          Byte      Item         Size   Description/Comments
  552.          0         Manufacturer  1     Constant Flag, 10 = ZSoft .pcx
  553.          1         Version       1     Version information
  554.                                        0 = Version 2.5 of PC Paintbrush
  555.                                        2 = Version 2.8 w/palette information
  556.                                        3 = Version 2.8 w/o palette information
  557.                                        4 = PC Paintbrush for Windows(Plus for
  558.                                            Windows uses Ver 5)
  559.                                        5 = Version 3.0 and > of PC Paintbrush
  560.                                            and PC Paintbrush +, includes
  561.                                            Publisher's Paintbrush . Includes
  562.                                            24-bit .PCX files
  563.          2         Encoding      1     1 = .PCX run length encoding
  564.          3         BitsPerPixel  1     Number of bits to represent a pixel
  565.                                        (per Plane) - 1, 2, 4, or 8
  566.          4         Window        8     Image Dimensions: Xmin,Ymin,Xmax,Ymax
  567.         12         HDpi          2     Horizontal Resolution of image in DPI*
  568.         14         VDpi          2     Vertical Resolution of image in DPI*
  569.         16         Colormap     48     Color palette setting
  570.         64         Reserved      1     Should be set to 0.
  571.         65         NPlanes       1     Number of color planes
  572.         66         BytesPerLine  2     Number of bytes to allocate for a
  573.                                        scanline plane.  MUST be an EVEN
  574.                                        number. Do NOT calculate from Xmax-Xmin.
  575.         68         PaletteInfo   2     How to interpret palette- 1 = Color/BW,
  576.                                        2 = Grayscale (ignored in PB IV/ IV +)
  577.         70         HscreenSize   2     Horizontal screen size in pixels. New
  578.                                        field found only in PB IV/IV Plus
  579.         72         VscreenSize   2     Vertical screen size in pixels. New
  580.                                        field found only in PB IV/IV Plus
  581.         74         Filler       54     Blank to fill out 128 byte header.  Set all
  582.                                        bytes to 0
  583.  
  584.     NOTES:
  585.  
  586.     All sizes are measured in BYTES.
  587.     All variables of SIZE 2 are integers.
  588.     *HDpi and VDpi represent the Horizontal and Vertical resolutions which the
  589.   image was created (either printer or scanner); i.e. an image which was
  590.   scanned might have 300 and 300 in each of these fields.
  591.  
  592.     Ok, if the above listing didn't gave you a clue, think of a PCX file like
  593.   this. It is a file composed in the following form. The first 128 bytes are
  594.   the header, which contains lots of informatation about the PCX file, like the
  595.   size of the picture, pallete information (in less than 256 color modes).
  596.   Then comes the picture data, encoded with a run-lenght algorythm... I will
  597.   explain this latter. Then comes a byte with the value 12, if a 256 color
  598.   palette exists. If it exists, it will be stored in the following 768 bytes.
  599.     To read a PCX file, you can do like this: first, set three records, like
  600.   this:
  601.  
  602.     Type RGBItem=Record
  603.                        Red:Byte;
  604.                        Green:Byte;
  605.                        Blue:Byte;
  606.                  End;
  607.  
  608.          PCXHeader=Record
  609.                          Manufacturer:Byte;
  610.                          Version:Byte;
  611.                          Encoding:Byte;
  612.                          BitsPerPixel:Byte;
  613.                          Window=Record
  614.                                       Xmin:Integer;
  615.                                       Ymin:Integer;
  616.                                       Xmax:Integer;
  617.                                       Ymax:Integer;
  618.                                 End;
  619.                          HDpi:Integer;
  620.                          VDpi:Integer;
  621.                          Colormap:Array[0..15] Of RgbItem;
  622.                          Reserved:Byte;
  623.                          NPlanes:Byte;
  624.                          BytesPerLine:Integer;
  625.                          PaletteInfo:Integer;
  626.                          HScreenSize:Integer;
  627.                          VScreenSize:Integer;
  628.                          Filler:Array[1..54] Of Byte;
  629.                    End;
  630.  
  631.          RGBList=Array[0..255] Of RGBItem;
  632.  
  633.     Then, you read the header. You can do it with this:
  634.  
  635.       Var Head:PCXHeader;
  636.       ......................
  637.       ......................
  638.       Assign(F,'IMAGE.PCX');
  639.       Reset(F,1);
  640.       BlockRead(F,Head,128);
  641.  
  642.     The above piece of code will read the header of the PCX file called
  643.   IMAGE.PCX. Now the variable Head, of type PCXHeader will contain all the
  644.   relevant data of the PCX file. In the example I will give you, we'll ignore
  645.   the header and assume the picture is a standard mode 13h image (because this
  646.   is a tutorial on mode 13h). But don't worry... Anything that will be said
  647.   here can be adapted to any graphic mode.
  648.  
  649.     5.3. Decoding a PCX file
  650.  
  651.     You can now begin decoding the first scan line - read the first byte of
  652.   data from the file. If the top two bits are set, the remaining six bits
  653.   in the byte show how many times to duplicate the next byte in the file.
  654.   If the top two bits are not set, the first byte is the data itself, with a
  655.   count of one. Continue decoding the rest of the file like this.
  656.     If you didn't understand what I was saying, think about this:
  657.     You read a byte from the disk. Let's call this value A. If A is greater
  658.   than 192, you read the next byte, and then you output it to the screen,
  659.   A-192 times. It all becomes clearer with the piece of code I include next.
  660.   This procedure is called LoadPCX, and it just requires the name of file.
  661.   I'll assume that the graphics mode is already set. This procedure ignores
  662.   the header and just reads mode13h files. The procedures PutPixel and
  663.   SetPallete are user-defined before the LoadPCX file.
  664.  
  665.   Procedure LoadPCX(Filename:String);
  666.   var Fil:File;
  667.       Dx,Dy:Word;
  668.       J,M:Byte;
  669.       Ph:Word;
  670.       Buff:Array[0..127] of byte;
  671.       PCXPal:RgbList;
  672.  
  673.   Begin
  674.        Assign(Fil,Filename);
  675.        Reset(Fil,1);
  676.        Blockread(Fil,Buf,128);
  677.        Dx:=0;
  678.        Dy:=0;
  679.        Repeat
  680.              Dx:=0;
  681.              Repeat
  682.                    BlockRead(Fil,J,1);
  683.                    If J>192 Then
  684.                    Begin
  685.                         BlockRead(Fil,M,1);
  686.                         Dec(J,192);
  687.                         For Ph:=1 To J Do
  688.                         Begin
  689.                              PutPixel(Dx,Dy,M);
  690.                              Inc(Dx);
  691.                         End;
  692.                    End
  693.                    Else
  694.                    Begin
  695.                         PutPixel(Dx,Dy,J);
  696.                         Inc(Dx);
  697.                    End;
  698.            Until Dx>=320;
  699.            Inc(Dy);
  700.      Until Dy=200;
  701.      BlockRead(Fil,M,1);
  702.      If M=12 Then
  703.      Begin
  704.           BlockRead(Fil,PCXPal,768);
  705.           For M:=0 To 255 Do
  706.           Begin
  707.                PCXPal[M].R:=PCXPal[M].R Div 4;
  708.                PCXPal[M].G:=PCXPal[M].G Div 4;
  709.                PCXPal[M].B:=PCXPal[M].B Div 4;
  710.           End;
  711.           SetPalette(PCXPal);
  712.      End;
  713.      Close(Fil);
  714.   End;
  715.  
  716.     In case you're wondering why did I, after I read the palette, divide it
  717.   all by four, I'll explain... The registers of the VGA Palette have
  718.   intensities that range from 0 to 63... The PCX file saves palette information
  719.   from 0 to 255. So, before you use the palette, you must divide it all by
  720.   four. I know it is stupid, but I didn't invented it !
  721.     Also, the above code is very slow, because you read the data from the file
  722.   one byte at a time. You can speed it up by creating a buffer that stores part
  723.   of the file in order to reduce disk access... The speed-up is tremendous !
  724.   I'll show how can it be done in next issue.
  725.  
  726.  
  727.   6. Hints and Tips
  728.  
  729.                 *   - Begginners tip
  730.                 **  - Medium tip
  731.                 *** - Advanced tip
  732.  
  733.  
  734.     - Forward keyword (*)
  735.  
  736.       If you write that following piece of code:
  737.  
  738.       Procedure One;
  739.       Begin
  740.            Two;
  741.       End;
  742.  
  743.       Procedure Two;
  744.       Begin
  745.       End;
  746.  
  747.       You would get an error, because when the compiler reaches to the call of
  748.       procedure Two in procedure One, he doesn't know yet procedure Two...
  749.       There are two ways of mending this. The first is to reverse the order the
  750.       procedures appear. The second comes in hand in cases like the following:
  751.  
  752.       Procedure One;
  753.       Begin
  754.            Two;
  755.       End;
  756.  
  757.       Procedure Two;
  758.       Begin
  759.            One;
  760.       End;
  761.  
  762.       I know this would get an infinite cicle, but that's beyond the point.
  763.       The only way to go around this is to use the forward keyword. The forward
  764.       keyword informs the compiler that a certain procedure exists, so it will
  765.       not give a 'Undefined Procedure' error. So, to validate the last piece
  766.       of code, you would have to do it like this:
  767.  
  768.       Procedure One; Forward;
  769.       Procedure Two; Forward;
  770.  
  771.       Procedure One;
  772.       Begin
  773.            Two;
  774.       End;
  775.  
  776.       Procedure Two;
  777.       Begin
  778.            One;
  779.       End;
  780.  
  781.     - Speeding up some routines (**)
  782.  
  783.       One way to optimize code is to calculate all the relevant stuff in an
  784.       inner loop before the loop. For example, let's assume we have the
  785.       following code:
  786.  
  787.       For A:=1 To 100 Do
  788.       Begin
  789.            For B:=1 To 200 Do
  790.            Begin
  791.                 C:=A*50+B;
  792.            End;
  793.       End;
  794.  
  795.       This could be replaced by this faster code:
  796.  
  797.       For A:=1 To 100 Do
  798.       Begin
  799.            D:=A*50;
  800.            For B:=1 To 200 Do
  801.            Begin
  802.                 C:=D+B;
  803.            End;
  804.       End;
  805.  
  806.       The only drawback is the use of an extra variable, but that's almost
  807.       always a constant... The more speed you want, the more memory you spend,
  808.       and vice-versa.
  809.  
  810.  
  811.   7. Points of view
  812.  
  813.     Well, I don't know what to talk about in this issue, so I think I'll 
  814.   just ramble on...
  815.     I'll start with a moan (as usual)... Why can't I get a musician and a 
  816.   Gfx artist for my productions ? I really want to do something like a 
  817.   demo or a game, but I can't because I can't do music and can't draw... 
  818.   And I don't have a computer good enough to run 3D Studio (the only 
  819.   drawing program I know that the person who uses it doesn't need to draw 
  820.   well to create a masterpiece...). 
  821.     Next, I'll send my respects to some demo and game making groups out 
  822.   there... Especially the ones that don't charge anything for their 
  823.   work... Not because I'm a cheap-stakes, it's just because those guys 
  824.   programm for their love for the art, not for love for the money... Of 
  825.   course, it isn't wrong to get money out of it... Money is good... But 
  826.   I admire more a guy that spends lots of time developing a program to 
  827.   release it free than I admire a guy that gets big bucks for doing the 
  828.   same thing.
  829.     And why every employer nowadays whats you to know Visual C/Basic, or 
  830.   Windows 95 programming and other user-friendly shit like that. I HATE 
  831.   WINDOWS... 95 and 3.1... I hate them all... They aren't made for 
  832.   programmers... They are made for users... But the worse is that one day, 
  833.   all that there is left is Win95... And we'll have to quit doing demos and 
  834.   games, because most demos/games use resources that Win95 don't allow you 
  835.   to use... It will be like a return to the stone-age in demo/game making.
  836.     I'm just too melodramatic today, ain't I ? :)
  837.   Weel, I don't know when the next issue will come, nor what will it 
  838.   have, so keep your eyes peeled for it. I think I'll put, in the begginers
  839.   part, a tutorial on how to create and use Pascal Units. In the graphics part
  840.   I think I'll make an article on scrolling and I'm also thinking on including
  841.   an article on Pointers (the second part of an article I've started in issue
  842.   one). I'll also will try to squeeze the first of the Spellcaster Utilities,
  843.   a series of programms to help you develop your programs. So I think the next
  844.   issue will take longer to make that I thought in the first place. I have to
  845.   code the first utilitie (I'm thinking about doing a palette editor).
  846.   I'll try to make the best I can, as usual... Send all doubts to me. And
  847.   your articles/articles suggestions.. I'd love to see them. I'll help if I
  848.   can.
  849.  
  850.  
  851.   8. The adventures of Spellcaster, the rebel programmer of year 2018.
  852.  
  853.   Episode 6 - Hear no evil, see no evil
  854.  
  855.     I looked at the clock. It was 7 a.m. Only an escape plan could make 
  856.   me rise so early. I looked at Karl. His eyes were very bright, as if he 
  857.   was starting to cry. I prefered to believe that it was the sun rising up 
  858.   ahead that was hurting his eyes.
  859.   - Let's go... - I said, starting to walk down the hill, in direction to 
  860.     the Sega Corporate Prison. I heard Gundsen's steps behind me.
  861.   - Are you sure the virus will work ? - he asked, with a little fear on 
  862.     his voice.
  863.   - Positive... I've run tests with it. Relax... If the virus is in the 
  864.     central computer, this will work...
  865.   - And if it isn't ?
  866.   - This will be the shortest jailbreak in history ! - I said with a dark 
  867.     voice.
  868.   - How did you got it into the system ?
  869.   - I sent a disk to the warden... He probably downloaded it in the main 
  870.     computer's memory.
  871.   - What ?!! - shouted Gundsen, stopping. - Don't you know they scan 
  872.     every disk with a virus-checker ?!
  873.   - Of course I know... Relax... My virus is undetectable... It is 
  874.     disguised like a game.
  875.   - Ok... Ok... - said Gundsen, starting to walk again.
  876.     We were almost two steps away from the wall of the prison, when Karl 
  877.   spotted a droid above the wall, with it's eyes fixed on our position.
  878.   - A guard drone... The prison is managed by them... - I said, in a 
  879.     normal voice. - I think it is deactivated by my virus... As all the 
  880.     other parts of the prison.
  881.     I took a lazer gun out of my pocket and I started blasting the 
  882.   wall... No guards appeared. It seemed my virus worked. We got into the 
  883.   prison, and within minutes, we opened the doors to every cell in the 
  884.   complex, making every prisoner there run away. I smiled, thinking of the 
  885.   work Comptel would have to arrest them all again...
  886.     Deathripper found his sister, and we all ran away to the the jetcar.
  887.     As we all returned to the Brotherhood of the Rebel Programmer home 
  888.   base, I was wondering if it was a good idea this new aquisition... 
  889.  
  890.                                              See you in the next issue
  891.                                             Diogo "SpellCaster" Andrade